`include "PRV564Config.v"
`include "PRV564Define.v"
//////////////////////////////////////////////////////////////////////////////////////////////////
//  Date    : 2021/7/5                                                                          //
//  Author  : Jack.Pan                                                                          //
//  Desc    : Trap Handle unit for PRV564 processor                                             //
//  Version : 0.0(Orignal)                                                                      //
//////////////////////////////////////////////////////////////////////////////////////////////////
module TrapHandle(
    input wire              CLKi, ARSTi,        //clock and global reset
    //---------------interrupt from platform controller-----
    input wire              Interrupt_MEI, Interrupt_MSI, Interrupt_MTI,
    input wire              Interrupt_SEI,
    //---------------csr value output-----------------
    output wire [`XLEN-1:0] mip, sip,
    output reg  [`XLEN-1:0] mscratch, mepc, mcause, mtval,
    output reg  [`XLEN-1:0] sscratch, sepc, scause, stval,
    //-----------write back to csr---------
    input wire [11:0]       csr_index,
    input wire [`XLEN-1:0]  csr_data,
    input wire              csr_wren,
    //-----------Trap value input----------
    input wire              trap_m, trap_s, trap_async,
    input wire [`XLEN-1:0]  trap_pc, trap_value, trap_cause
);
//---------------mip and sip---------------------
    //seip有两个寄存器组成：seip1是真实的外部中断，seip2是被读写的外部中断
    //S模式的中断等待信息是被M模式读写的
    reg ip_meip, ip_msip, ip_mtip, ip_seip1, ip_seip2, ip_ssip, ip_stip;
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        ip_seip2<= 1'b0;
        ip_ssip <= 1'b0;
        ip_stip <= 1'b0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mip_index)begin
            ip_seip2<= csr_data[9];
            ip_stip <= csr_data[5];
            ip_ssip <= csr_data[1];
        end
    end
end
    //M模式的中断，和S模式的外部中断是外部中断控制器发出的，内部只读
always@(posedge CLKi)begin
    ip_meip <= Interrupt_MEI;
    ip_msip <= Interrupt_MSI;
    ip_mtip <= Interrupt_MTI;
    ip_seip1<= Interrupt_SEI;
end
assign mip = {52'b0,ip_meip,1'b0,(ip_seip1|ip_seip2),1'b0,ip_mtip,1'b0,ip_stip,1'b0,ip_msip,1'b0,ip_ssip,1'b0};
assign sip = {54'b0,(ip_seip1|ip_seip2),3'b0,ip_stip,3'b0,ip_ssip,1'b0};
//-------------mscratch and sscratch--------------
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        mscratch <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mscratch_index)begin
            mscratch <= csr_data;
        end
    end
end
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        sscratch <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `srw_sscratch_index)begin
            sscratch <= csr_data;
        end
    end
end
//-------------mepc and sepc-----------------
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        mepc <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mepc_index)begin
            mepc <= csr_data;
        end
    end
    else if(trap_m)begin
        mepc <= trap_pc;
    end
end
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        sepc <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `srw_sepc_index)begin
            sepc <= csr_data;
        end
    end
    else if(trap_s)begin
        sepc <= trap_pc;
    end
end
//--------------mcause and scause----------------
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        mcause <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mcause_index)begin
            mcause <= csr_data;
        end
    end
    else if(trap_m)begin
        mcause <= trap_async ? {1'b1,trap_cause[62:0]} : trap_cause;
    end
end
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        scause <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `srw_scause_index)begin
            scause <= csr_data;
        end
    end
    else if(trap_s)begin
        scause <= trap_async ? {1'b1,trap_cause[62:0]} : trap_cause;
    end
end
//-----------------tval--------------------------
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        mtval <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `mrw_mtval_index)begin
            mtval <= csr_data;
        end
    end
    else if(trap_m)begin
        mtval <= trap_value;
    end
end
always@(posedge CLKi or posedge ARSTi)begin
    if(ARSTi)begin
        stval <= 'h0;
    end
    else if(csr_wren)begin
        if(csr_index == `srw_stval_index)begin
            stval <= csr_data;
        end
    end
    else if(trap_s)begin
        stval <= trap_value;
    end
end

endmodule
